class Canvas {
    constructor(canvasElement) {
        this.canvas = canvasElement;
        this.context = this.canvas.getContext('2d');
        this.objects = [];
        this.activeObject = null;
        this.dragOffsetX = 0;
        this.dragOffsetY = 0;
        this.isDragging = false;
        this.isResizing = false;
        this.initEventListeners();
        this.eventListeners = {}; // 添加事件监听器集合

        // 新增
        this.isMultiTouch = false;
        this.initialTouchDistance = 0;
        this.initialTouchAngle = 0;
        this.initialWidth = 0;
        this.initialHeight = 0;
        this.initialAngle = 0;
        this.initialCenter = { x: 0, y: 0 };
    }

    getContext() {
        return this.context;
    }
    renderAll() {
        this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
        for (const obj of this.objects) {
            obj.render(this.context, this);
        }
        // 单独绘制选中对象的选中状态，确保在最上层
        for (const obj of this.objects) {
            if (obj.isSelected) {
                obj._renderSelection(this.context, this);
            }
        }
    }

    add(object) {
        this.objects.push(object);
        this.renderAll();
    }

    remove(object) {
        const index = this.objects.indexOf(object);
        if (index > -1) {
            this.objects.splice(index, 1);
        }
        this.renderAll();
    }

    setActiveObject(object) {
        if (this.activeObject) {
            this.activeObject.isSelected = false;
        }
        this.activeObject = object;
        if (this.activeObject) {
            this.activeObject.isSelected = true;
        }

        this.renderAll();

        this.trigger('object:selected', object); // 触发对象选中事件
    }

    getActiveObject() {
        return this.activeObject;
    }

    toJSON() {
        return JSON.stringify({
            objects: this.objects,
            version: '1.0.0',
        });
    }

    loadFromJSON(json, callback) {
        const data = JSON.parse(json);
        this.objects = data.objects.map((objData) => {
            let obj;
            switch (objData.type) {
                case 'image':
                    obj = new ImageWedge(objData);
                    break;
                case 'text':
                    obj = new TextWedge(objData);
                    break;
                default:
                    return null;
            }
            return obj;
        });
        this.renderAll();
        if (callback) callback();
    }

    getWidth() {
        return this.canvas.width;
    }

    getHeight() {
        return this.canvas.height;
    }

    initEventListeners() {
        // 鼠标事件
        this.canvas.addEventListener('mousedown', this.onMouseDown.bind(this));
        this.canvas.addEventListener('mousemove', this.onMouseMove.bind(this));
        this.canvas.addEventListener('mouseup', this.onMouseUp.bind(this));

        // 触摸事件
        this.canvas.addEventListener('touchstart', this.onTouchStart.bind(this));
        this.canvas.addEventListener('touchmove', this.onTouchMove.bind(this));
        this.canvas.addEventListener('touchend', this.onTouchEnd.bind(this));
    }

    onMouseDown(event) {
        // console.log(event)
        const { offsetX, offsetY } = event;

        let activeObject = null;
        let lastActive = null;
        let button;
        if (this.activeObject) {
            button = this.activeObject.buttonContains(offsetX, offsetY);
            if (button) {
                activeObject = this.activeObject;
                lastActive = this.activeObject;
            }
        }

        if (!activeObject) {
            for (let i = this.objects.length - 1; i >= 0; i--) {
                const obj = this.objects[i];
                if (obj.isSelectable() && obj.contains(offsetX, offsetY)) {
                    activeObject = obj;
                    break;
                }
            }
        }

        if (activeObject) {
            this.setActiveObject(activeObject);
            this.dragOffsetX = offsetX - activeObject.x;
            this.dragOffsetY = offsetY - activeObject.y;
            this.isDragging = true;

            if (lastActive) {
                // 此处不需要对button区域重复验证，避免onClick执行两次
                // let button = activeObject.buttonContains(offsetX, offsetY)
                if (button) {
                    // console.log(button);
                    if (button.action === 'delete') {
                        this.remove(activeObject);
                        this.setActiveObject(null);
                    } else if (button.action === 'resize') {
                        this.isResizing = true;
                        this.initialWidth = activeObject.width;
                        this.initialHeight = activeObject.height;
                        this.initialMouseX = offsetX;
                        this.initialMouseY = offsetY;
                        this.initialAngle = activeObject.angle;
                        this.rotationCenterX = activeObject.x + activeObject.rotationCenterX;
                        this.rotationCenterY = activeObject.y + activeObject.rotationCenterY;
                    }
                }
            }
            return;
        }

        this.setActiveObject(null);
    }

    onMouseMove(event) {
        const { offsetX, offsetY } = event;

        if (this.isDragging && this.activeObject && !this.isResizing) {
            this.activeObject.x = offsetX - this.dragOffsetX;
            this.activeObject.y = offsetY - this.dragOffsetY;
            this.renderAll();
            this.trigger('object:moved', this.activeObject); // 触发对象移动事件
        } else if (this.isResizing && this.activeObject) {
            // 计算旋转中心到鼠标的角度
            const centerX = this.rotationCenterX;
            const centerY = this.rotationCenterY;
            const initialAngle = Math.atan2(this.initialMouseY - centerY, this.initialMouseX - centerX);
            const currentAngle = Math.atan2(offsetY - centerY, offsetX - centerX);
            const angleDelta = currentAngle - initialAngle;

            // 计算新的宽度和高度
            const initialDistance = Math.sqrt(
                (this.initialMouseX - centerX) ** 2 + (this.initialMouseY - centerY) ** 2
            );
            const currentDistance = Math.sqrt((offsetX - centerX) ** 2 + (offsetY - centerY) ** 2);
            const scale = currentDistance / initialDistance;
            const newWidth = this.initialWidth * scale;
            const newHeight = this.initialHeight * scale;

            // 更新角度和尺寸
            this.activeObject.angle = this.initialAngle + (angleDelta * 180) / Math.PI;
            this.activeObject.updateRotationCenter(newWidth, newHeight);

            // 更新字体大小
            if (this.activeObject instanceof TextWedge) {
                this.activeObject.updateFontSize();
            }

            this.renderAll();

            this.trigger('object:rotated', this.activeObject); // 触发对象旋转事件
        }
    }

    onMouseUp(event) {
        this.isDragging = false;
        this.isResizing = false;
    }

    onTouchStart(event) {
        event.preventDefault(); // 阻止默认行为（如滚动）

        if (event.touches.length === 1) {
            const touch = event.touches[0];
            const { clientX, clientY } = touch;
            const { left, top } = this.canvas.getBoundingClientRect();
            const offsetX = clientX - left;
            const offsetY = clientY - top;

            this.onMouseDown({ offsetX, offsetY });
        } else if (event.touches.length === 2) {
            this.isMultiTouch = true;
            this.initialTouchDistance = this.getTouchDistance(event);
            this.initialTouchAngle = this.getTouchAngle(event);
            this.initialCenter = this.getTouchCenter(event);

            if (this.activeObject) {
                this.initialWidth = this.activeObject.width;
                this.initialHeight = this.activeObject.height;
                this.initialAngle = this.activeObject.angle;
                this.initialObjectCenter = {
                    x: this.activeObject.x + this.activeObject.rotationCenterX,
                    y: this.activeObject.y + this.activeObject.rotationCenterY,
                };
            }
        }
    }

    onTouchMove(event) {
        event.preventDefault();

        if (event.touches.length === 1 && !this.isMultiTouch) {
            const touch = event.touches[0];
            const { clientX, clientY } = touch;
            const { left, top } = this.canvas.getBoundingClientRect();
            const offsetX = clientX - left;
            const offsetY = clientY - top;

            this.onMouseMove({ offsetX, offsetY });
        } else if (event.touches.length === 2 && this.isMultiTouch) {
            const currentDistance = this.getTouchDistance(event);
            const currentAngle = this.getTouchAngle(event);
            const currentCenter = this.getTouchCenter(event);

            const scale = currentDistance / this.initialTouchDistance;
            const angleDelta = currentAngle - this.initialTouchAngle;

            if (this.activeObject) {
                const newWidth = this.initialWidth * scale;
                const newHeight = this.initialHeight * scale;

                // Update the object's width, height, and angle
                this.activeObject.width = newWidth;
                this.activeObject.height = newHeight;
                this.activeObject.angle = this.initialAngle + angleDelta;

                // Move the object to keep the center of rotation at the center of the two touches
                const dx = currentCenter.x - this.initialCenter.x;
                const dy = currentCenter.y - this.initialCenter.y;
                this.activeObject.x = this.initialObjectCenter.x - this.activeObject.rotationCenterX + dx;
                this.activeObject.y = this.initialObjectCenter.y - this.activeObject.rotationCenterY + dy;

                this.renderAll();
            }
        }
    }

    onTouchEnd(event) {
        event.preventDefault();
        if (event.touches.length === 0) {
            this.isMultiTouch = false;
        }
        this.onMouseUp(event);
    }

    getTouchDistance(event) {
        const touch1 = event.touches[0];
        const touch2 = event.touches[1];
        const dx = touch2.clientX - touch1.clientX;
        const dy = touch2.clientY - touch1.clientY;
        return Math.sqrt(dx * dx + dy * dy);
    }

    getTouchAngle(event) {
        const touch1 = event.touches[0];
        const touch2 = event.touches[1];
        const dx = touch2.clientX - touch1.clientX;
        const dy = touch2.clientY - touch1.clientY;
        return Math.atan2(dy, dx) * (180 / Math.PI);
    }

    getTouchCenter(event) {
        const touch1 = event.touches[0];
        const touch2 = event.touches[1];
        return {
            x: (touch1.clientX + touch2.clientX) / 2,
            y: (touch1.clientY + touch2.clientY) / 2,
        };
    }

    // 注册事件监听器
    on(event, callback) {
        if (!this.eventListeners[event]) {
            this.eventListeners[event] = [];
        }
        this.eventListeners[event].push(callback);
    }

    // 触发事件
    trigger(event, data) {
        if (this.eventListeners[event]) {
            this.eventListeners[event].forEach((callback) => callback(data));
        }
    }
}
